/**
 * ProxyManager.java
 * 2007-12-4 ����05:48:45
 * Author: Lex
 * Note:
 */
package org.lex.net.proxy;

import java.net.Proxy;
import java.util.ArrayList;
import java.util.List;

import javax.swing.event.EventListenerList;
import javax.swing.table.AbstractTableModel;

public class ProxyManager extends AbstractTableModel {
	private static final int DEFAULT_PROXY_COUNT = 4;
	private static final String[] COLUMN_NAMES = { "Status", "Name", "Type", "Server", "Port" };
	// ===============================================
	private List<ProxyServer> proxies = null;
	private Proxy currentProxy = null;
	private int currentIndex = 0;
	// ===========================
	// proxy change event support
	private EventListenerList listenerList = null;

	public ProxyManager() {
		super();
		this.proxies = new ArrayList<ProxyServer>(DEFAULT_PROXY_COUNT);
		this.proxies.add(ProxyServer.DIRECT);
		this.currentProxy = Proxy.NO_PROXY;
		this.currentIndex = 0;
		this.listenerList = new EventListenerList();
	}

	public void put(ProxyServer ps) {
		if (null == ps)
			return;
		String name = ps.getName();
		if ("".equals(name) || ProxyServer.DIRECT.getName().equals(name))
			return;
		// ==================================
		int row = this.indexOf(name);
		if (-1 == row) {
			proxies.add(ps);
			row = proxies.size() - 1;
		} else {
			proxies.set(row, ps);
		}
		this.fireTableRowsUpdated(row, row);
		if (row == this.currentIndex)
			this.fireProxyChanged(ps.getProxy());
	}

	public ProxyServer remove(String name) {
		if (null == name || "".equals(name))
			return null;
		int row = this.indexOf(name);
		if (-1 != row)
			return proxies.remove(row);
		return null;
	}

	public boolean setUsingProxy(String name) {
		int row = this.indexOf(name);
		if (-1 == row)
			return false;
		ProxyServer ps = proxies.get(row);
		if (null == ps.getProxy())
			throw new NullPointerException("ProxyServer could not be null");
		this.fireTableCellUpdated(this.currentIndex, 0);
		this.currentProxy = ps.getProxy();
		this.currentIndex = row;
		this.fireTableCellUpdated(this.currentIndex, 0);
		this.fireProxyChanged(ps.getProxy());
		return true;
	}

	public Proxy getProxy() {
		return this.currentProxy;
	}

	public String getProxyName() {
		return this.proxies.get(this.currentIndex).getName();
	}

	// proxy change event support
	public void addProxyListener(ProxyListener listener) {
		this.listenerList.add(ProxyListener.class, listener);
	}

	public void removeProxyListener(ProxyListener listener) {
		this.listenerList.remove(ProxyListener.class, listener);
	}

	protected void fireProxyChanged(Proxy proxy) {
		// Guaranteed to return a non-null array
		Object[] listeners = listenerList.getListenerList();
		// Process the listeners last to first, notifying
		// those that are interested in this event
		ProxyEvent event = null;
		for (int i = listeners.length - 2; i >= 0; i -= 2) {
			if (listeners[i] == ProxyListener.class) {
				// Lazily create the event:
				if (event == null)
					event = new ProxyEvent(proxy);
				((ProxyListener) listeners[i + 1]).proxyChanged(event);
			}
		}
	}

	// TableModel
	@Override
	public int getColumnCount() {
		return COLUMN_NAMES.length;
	}

	@Override
	public int getRowCount() {
		return proxies.size();
	}

	@Override
	public String getColumnName(int column) {
		return COLUMN_NAMES[column];
	}

	@Override
	public Class<?> getColumnClass(int column) {
		switch (column) {
		case 0:
			return Boolean.class;
		case 1:
			return String.class;
		case 2:
			return Proxy.Type.class;
		case 3:
			return String.class;
		case 4:
			return Integer.class;
		default:
			return Object.class;
		}
	}

	@Override
	public Object getValueAt(int row, int column) {
		if (0 == column) {
			if (row == this.currentIndex)
				return Boolean.TRUE;
			else
				return Boolean.FALSE;
		}
		ProxyServer ps = this.proxies.get(row);
		switch (column) {
		case 1:
			// name
			return ps.getName();
		case 2:
			// type
			return ps.getProxy().type();
		case 3:
			// host
			return ps.getHost();
		case 4:
			// port
			return ps.getPort();
		}
		return null;
	}

	private int indexOf(String name) {
		if (null == name || 0 == name.length())
			throw new NullPointerException("Proxy name could not be null");
		int count = proxies.size();
		for (int i = 0; i < count; i++) {
			ProxyServer p = proxies.get(i);
			if (p.getName().equals(name))
				return i;
		}
		return -1;
	}
}
